﻿/*
 * chunk是RIFF文件的基本单元
 */

using System;
using System.IO;

namespace RIFF.Chunk
{
    /// <summary>
    /// 基础 Chunk
    /// </summary>
    public class Chunk
    {
        /// <summary>
        /// 访问 RIFF 文件的流
        /// </summary>
        protected readonly Stream stream;

        /// <summary>
        /// Data 字段在 stream 中的起始位置
        /// </summary>
        protected readonly long dataPosition;

        /// <summary>
        /// Chunk 的 Id
        /// </summary>
        public FourCC Id { get; }

        /// <summary>
        /// Data 字段字节数，不包括 Id、Size
        /// </summary>
        public int Size { get; protected set; }

        /// <summary>
        /// 返回 Chunk 的 Data 字段值
        /// </summary>
        /// <returns>Chunk 的 Data 字段值</returns>
        public byte[] GetData()
        {
            var keepPosition = stream.Position;
            stream.Position = dataPosition;

            var data = new byte[Size];
            stream.Read(data);

            stream.Position = keepPosition;
            return data;
        }

        /// <summary>
        /// 克隆另一个 Chunk
        /// </summary>
        /// <param name="chunk">克隆源</param>
        protected Chunk(Chunk chunk)
        {
            Id = chunk.Id;
            Size = chunk.Size;
            stream = chunk.stream;
            dataPosition = chunk.dataPosition;
        }

        /// <summary>
        /// 从 stream 的当前读写位置构造一个 Chunk
        /// </summary>
        /// <param name="stream"></param>
        public Chunk(Stream stream)
        {
            this.stream = stream;

            var buf = new byte[4];
            stream.Read(buf);
            Id = new FourCC(buf);

            stream.Read(buf);
            Size = BitConverter.ToInt32(buf);
            dataPosition = stream.Position;
            stream.Position += Size;
        }



        /// <summary>
        /// 转换至 RIFF Chunk，将详细解析 Data 字段
        /// </summary>
        /// <returns>Riff</returns>
        public Riff ToRiffChunk()
        {
            return new Riff(this);
        }

        /// <summary>
        /// 转换至 List Chunk，将详细解析 Data 字段
        /// </summary>
        /// <exception cref="CreateChunkException"/>
        /// <returns>List</returns>
        public List ToListChunk()
        {
            try
            {
                return new List(this);
            }
            catch (Exception ex)
            {
                throw new CreateChunkException(typeof(List), ex);
            }
        }

        /// <summary>
        /// 转换至 Data Chunk，将详细解析 Data 字段
        /// </summary>
        /// <exception cref="CreateChunkException"/>
        /// <returns>Data</returns>
        public Data ToDataChunk()
        {
            try
            {
                return new Data(this);
            }
            catch (Exception ex)
            {
                throw new CreateChunkException(typeof(Data), ex);
            }
        }

        /// <summary>
        /// 转换至 Fact Chunk，将详细解析 Data 字段
        /// </summary>
        /// <exception cref="CreateChunkException"/>
        /// <returns>Fact</returns>
        public Fact ToFactChunk()
        {
            try
            {
                return new Fact(this);
            }
            catch (Exception ex)
            {
                throw new CreateChunkException(typeof(Fact), ex);
            }
        }

        /// <summary>
        /// 转换至 Format Chunk，将详细解析 Data 字段
        /// </summary>
        /// <exception cref="CreateChunkException"/>
        /// <returns>Format</returns>
        public Format ToFormatChunk()
        {
            try
            {
                return new Format(this);
            }
            catch (Exception ex)
            {
                throw new CreateChunkException(typeof(Format), ex);
            }
        }
    }
}
